/**
 * elancom Corporation copy right 2012 - 2015  
 *   
 * $Header: https://192.168.1.224/svn/elancom/product/elancom-platform/trunk/src/main/java/com/elancom/framework/commons/json/parser/deserializer/ASMJavaBeanDeserializer.java 1034 2012-07-02 03:09:12Z lanzhouxue $
 * $Id: ASMJavaBeanDeserializer.java 1034 2012-07-02 03:09:12Z lanzhouxue $
 * $Author: lanzhouxue $
 * $Date: 2012-07-02 11:09:12 +0800 (Mon, 02 Jul 2012) $
 * $Revision: 1034 $
 */
package com.elancom.framework.commons.json.parser.deserializer;

import java.lang.reflect.Type;
import java.util.Map;

import com.elancom.framework.commons.json.JSONException;
import com.elancom.framework.commons.json.parser.DefaultJSONParser;
import com.elancom.framework.commons.json.parser.Feature;
import com.elancom.framework.commons.json.parser.JSONScanner;
import com.elancom.framework.commons.json.parser.ParserConfig;
import com.elancom.framework.commons.json.util.FieldInfo;

public abstract class ASMJavaBeanDeserializer implements ObjectDeserializer {

	protected InnerJavaBeanDeserializer serializer;

	public ASMJavaBeanDeserializer(ParserConfig mapping, Class<?> clazz) {
		serializer = new InnerJavaBeanDeserializer(mapping, clazz);

		serializer.getFieldDeserializerMap();
	}

	public abstract Object createInstance(DefaultJSONParser parser, Type type);

	public InnerJavaBeanDeserializer getInnterSerializer() {
		return serializer;
	}

	@Override
	@SuppressWarnings("unchecked")
	public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
		return (T) serializer.deserialze(parser, type, fieldName);
	}

	@Override
	public int getFastMatchToken() {
		return serializer.getFastMatchToken();
	}

	public Object createInstance(DefaultJSONParser parser) {
		return serializer.createInstance(parser, serializer.getClazz());
	}

	public FieldDeserializer createFieldDeserializer(ParserConfig mapping, Class<?> clazz, FieldInfo fieldInfo) {
		return mapping.createFieldDeserializer(mapping, clazz, fieldInfo);
	}

	public FieldDeserializer getFieldDeserializer(String name) {
		return serializer.getFieldDeserializerMap().get(name);
	}

	public Type getFieldType(String name) {
		return serializer.getFieldDeserializerMap().get(name).getFieldType();
	}

	public boolean parseField(DefaultJSONParser parser, String key, Object object, Type objectType, Map<String, Object> fieldValues) {
		final JSONScanner lexer = (JSONScanner) parser.getLexer(); // xxx

		final Map<String, FieldDeserializer> feildDeserializerMap = serializer.getFieldDeserializerMap();
		FieldDeserializer fieldDeserializer = feildDeserializerMap.get(key);

		if (fieldDeserializer == null) {
			for (final Map.Entry<String, FieldDeserializer> entry : feildDeserializerMap.entrySet()) {
				if (entry.getKey().equalsIgnoreCase(key)) {
					fieldDeserializer = entry.getValue();
					break;
				}
			}
		}

		if (fieldDeserializer == null) {
			if (!parser.isEnabled(Feature.IgnoreNotMatch)) {
				throw new JSONException("setter not found, class " + serializer.getClass() + ", property " + key);
			}

			lexer.nextTokenWithColon();
			parser.parse(); // skip

			return false;
		}

		lexer.nextTokenWithColon(fieldDeserializer.getFastMatchToken());
		fieldDeserializer.parseField(parser, object, objectType, fieldValues);
		return true;
	}

	public final class InnerJavaBeanDeserializer extends JavaBeanDeserializer {

		private InnerJavaBeanDeserializer(ParserConfig mapping, Class<?> clazz) {
			super(mapping, clazz);
		}

		@Override
		public boolean parseField(DefaultJSONParser parser, String key, Object object, Type objectType, Map<String, Object> fieldValues) {
			return ASMJavaBeanDeserializer.this.parseField(parser, key, object, objectType, fieldValues);
		}

		@Override
		public FieldDeserializer createFieldDeserializer(ParserConfig mapping, Class<?> clazz, FieldInfo fieldInfo) {
			return ASMJavaBeanDeserializer.this.createFieldDeserializer(mapping, clazz, fieldInfo);
		}
	}

}
